package com.symaster.common.geom;

import com.symaster.common.geom.entity.LineSegment;
import com.symaster.common.geom.entity.Polygon;
import com.symaster.common.geom.entity.Vector;
import com.symaster.common.geom.util.PointUtil;
import com.symaster.common.swing.util.SwingUtil;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.List;

/**
 * @author yinmiao
 * @version 2022-07-15 19:55
 */
public class PolygonPointEditing extends JComponent {
    private JPanel root_panel;
    private JScrollPane scroll_pane;
    private JCheckBox drawLineVCheckBox;
    private JCheckBox drawLineHCheckBox;
    private final PolygonPane polygonPane;
    private final Polygon polygon;
    private double size;

    public static void show(Polygon polygon) {
        PolygonPointEditing polygonPointEditing = new PolygonPointEditing(polygon);
        JDialog jDialog = new JDialog();
        jDialog.setContentPane(polygonPointEditing);
        jDialog.setPreferredSize(new Dimension(1620, 940));
        jDialog.pack();
        SwingUtil.toCenter(jDialog);
        jDialog.setVisible(true);
    }

    public PolygonPointEditing(Polygon polygon) {
        this.polygon = polygon;
        this.size = 1500;
        setLayout(new BorderLayout());
        add(root_panel, BorderLayout.CENTER);
        polygonPane = new PolygonPane();
        Dimension dimension = new Dimension(1500, 1500);
        polygonPane.setPreferredSize(dimension);
        polygonPane.setSize(dimension);
        drawLineVCheckBox.setSelected(polygonPane.drawLineV);
        drawLineHCheckBox.setSelected(polygonPane.drawLineH);
        scroll_pane.setViewportView(polygonPane);
        scroll_pane.getHorizontalScrollBar().setUnitIncrement(20);
        scroll_pane.getVerticalScrollBar().setUnitIncrement(20);
        update();

        drawLineVCheckBox.addActionListener(e -> {
            polygonPane.drawLineV = drawLineVCheckBox.isSelected();
            polygonPane.repaint();
        });
        drawLineHCheckBox.addActionListener(e -> {
            polygonPane.drawLineH = drawLineHCheckBox.isSelected();
            polygonPane.repaint();
        });
    }

    public void update() {
        Polygon clone = polygon.clone();
        clone.scaleTransform(new com.symaster.common.geom.entity.Point(0, 0), PointUtil.getScale(Math.max(polygon.getWidth(), polygon.getHeight()), size));

        double xn = polygonPane.getWidth() / 2.0;
        double yn = polygonPane.getHeight() / 2.0;

        System.out.println(clone.getCenter());
        Vector translateVector = PointUtil.getTranslateVector(clone.getCenter(), new com.symaster.common.geom.entity.Point(xn, yn));
        clone.translate(translateVector);

        polygonPane.update(clone);
    }

    static class PolygonPane extends JComponent {

        private Polygon polygon;
        private static final int similarityEpsilon = 15;
        private static final double rotateSimilarityEpsilon = 15.0;
        private Boolean drawLineV = true;
        private Boolean drawLineH = true;
        private Boolean drawRotateSimilarityLine = false;

        public Boolean getDrawRotateSimilarityLine() {
            return drawRotateSimilarityLine;
        }

        public void setDrawRotateSimilarityLine(Boolean drawRotateSimilarityLine) {
            this.drawRotateSimilarityLine = drawRotateSimilarityLine;
        }

        public Boolean getDrawLineV() {
            return drawLineV;
        }

        public void setDrawLineV(Boolean drawLineV) {
            this.drawLineV = drawLineV;
        }

        public Boolean getDrawLineH() {
            return drawLineH;
        }

        public void setDrawLineH(Boolean drawLineH) {
            this.drawLineH = drawLineH;
        }

        public void update(Polygon polygon) {
            // Dimension size1 = getSize();

            // int min = Math.min(size1.width, size1.height) - 100;
            // double max = Math.max(polygon.getWidth(), polygon.getHeight());
            // double v = Math.max(max, min) / Math.min(max, min);

            this.polygon = polygon.clone();
            // this.polygon.scaleTransform(new com.symaster.common.geom.entity.Point(0, 0), v);

            repaint();
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            g.setColor(new Color(30, 30, 30));
            g.fillRect(0, 0, getWidth(), getHeight());

            if (polygon != null) {
                g.setColor(new Color(244, 244, 244));
                java.awt.Polygon polygon1 = polygon.toAwtPolygon();
                g.drawPolygon(polygon1);
                com.symaster.common.geom.entity.Point center = polygon.getCenter();
                Point point = center.toAwtPoint();
                g.drawLine(point.x - 10, point.y, point.x + 10, point.y);
                g.drawLine(point.x, point.y - 10, point.x, point.y + 10);

                if (drawLineV || drawLineH) {
                    LineSegment p2YLine = new LineSegment(new com.symaster.common.geom.entity.Point(polygon.getX() - 100, polygon.getY() + polygon.getHeight() / similarityEpsilon / 2.0), new com.symaster.common.geom.entity.Point(polygon.getX() + polygon.getWidth() + 100, polygon.getY() + polygon.getHeight() / similarityEpsilon / 2.0));
                    LineSegment p2XLine = new LineSegment(new com.symaster.common.geom.entity.Point(polygon.getX() + polygon.getWidth() / similarityEpsilon / 2.0, polygon.getY() - 100), new com.symaster.common.geom.entity.Point(polygon.getX() + polygon.getWidth() / similarityEpsilon / 2.0, polygon.getY() + polygon.getHeight() + 100));
                    double yOffset = polygon.getHeight() / similarityEpsilon;
                    double xOffset = polygon.getWidth() / similarityEpsilon;
                    for (int i = 0; i < similarityEpsilon; i++) {
                        if (i != 0) {
                            p2YLine.translate(0.0D, yOffset);
                            p2XLine.translate(xOffset, 0.0D);
                        }
                        g.setColor(new Color(120, 120, 120));
                        /* hLine */
                        if (drawLineV) {
                            Point point3 = p2XLine.getStartPoint().toAwtPoint();
                            Point point4 = p2XLine.getEndPoint().toAwtPoint();
                            g.drawLine(point3.x, point3.y, point4.x, point4.y);
                        }
                        /* vLine */
                        if (drawLineH) {
                            Point point5 = p2YLine.getStartPoint().toAwtPoint();
                            Point point6 = p2YLine.getEndPoint().toAwtPoint();
                            g.drawLine(point5.x, point5.y, point6.x, point6.y);
                        }

                        g.setColor(new Color(0, 255, 0));
                        if (drawLineV) {
                            List<com.symaster.common.geom.entity.Point> hPoints = polygon.getCrossPoint(p2XLine);
                            drawPoint(g, hPoints);
                        }
                        if (drawLineH) {
                            List<com.symaster.common.geom.entity.Point> vPoint = polygon.getCrossPoint(p2YLine);
                            drawPoint(g, vPoint);
                        }
                    }
                }

                if (drawRotateSimilarityLine) {
                    LineSegment line2 = new LineSegment(new com.symaster.common.geom.entity.Point(polygon.getX() - 100, polygon.getY() - 100), new com.symaster.common.geom.entity.Point(polygon.getX() + polygon.getWidth() + 100, polygon.getY() + polygon.getHeight() + 100));
                    int round = (int) Math.round(360 / rotateSimilarityEpsilon);
                    for (int i = 0; i < round; i++) {
                        if (i != 0) {
                            line2.rotate(line2.center(), rotateSimilarityEpsilon);
                        }
                        Point point2 = line2.getStartPoint().toAwtPoint();
                        Point point1 = line2.getEndPoint().toAwtPoint();
                        g.setColor(new Color(120, 120, 120));
                        g.drawLine(point2.x, point2.y, point1.x, point1.y);

                        g.setColor(new Color(0, 255, 0));
                        List<com.symaster.common.geom.entity.Point> crossPoint = polygon.getCrossPoint(line2);
                        drawPoint(g, crossPoint);
                    }
                }

                int[] xPoints = polygon1.xpoints;
                int[] yPoints = polygon1.ypoints;
                g.setColor(new Color(255, 0, 38));
                for (int i = 0; i < xPoints.length; i++) {
                    int x = xPoints[i];
                    int y = yPoints[i];
                    g.drawRect(x, y, 0, 0);
                }

            }
        }

        private void drawPoint(Graphics g, List<com.symaster.common.geom.entity.Point> hPoints) {
            Point[] points = hPoints.stream().map(com.symaster.common.geom.entity.Point::toAwtPoint).toArray(Point[]::new);
            drawPoints(g, points);
        }

        private void drawPoints(Graphics g, Point... points) {
            for (Point point : points) {
                g.drawRect(point.x - 1, point.y - 1, 2, 2);
            }
        }
    }

    static class Canvas extends JComponent {

        private final Image image;
        private final Graphics graphics;
        private final int w;
        private final int h;

        public Canvas(int w, int h) {
            this.w = w;
            this.h = h;
            SwingUtil.CanvasImage canvasImage = SwingUtil.createCanvasImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
            image = canvasImage.getImage();
            graphics = canvasImage.getGraphics();
        }

        public void draw(Polygon polygon) {
            graphics.setColor(new Color(255, 255, 255));
            graphics.fillRect(0, 0, w, h);

            Polygon clone = polygon.clone();
            java.awt.Polygon p1 = clone.toAwtPolygon();
            graphics.setColor(new Color(60, 60, 60));
            graphics.fillPolygon(p1);

            double scaleX = PointUtil.getScale(clone.getWidth(), clone.getWidth() - 1);
            double scaleY = PointUtil.getScale(clone.getHeight(), clone.getHeight() - 1);
            java.awt.Polygon p2 = PointUtil.scaleTransform(clone, scaleX, scaleY).toAwtPolygon();

            graphics.setColor(new Color(0, 0, 0));
            graphics.drawPolygon(p2);

            int[] xPoints = p2.xpoints;
            int[] yPoints = p2.ypoints;

            graphics.setColor(new Color(121, 222, 81));
            for (int i = 0; i < xPoints.length; i++) {
                int x = xPoints[i];
                int y = yPoints[i];
                graphics.drawRect(x - 1, y - 1, 3, 3);
            }
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            g.drawImage(image, 0, 0, null);
        }
    }

    {
        // GUI initializer generated by IntelliJ IDEA GUI Designer
        // >>> IMPORTANT!! <<<
        // DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        root_panel = new JPanel();
        root_panel.setLayout(new BorderLayout(0, 0));
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new BorderLayout(0, 0));
        panel1.setPreferredSize(new Dimension(0, 10));
        root_panel.add(panel1, BorderLayout.NORTH);
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new BorderLayout(0, 0));
        panel2.setPreferredSize(new Dimension(10, 0));
        root_panel.add(panel2, BorderLayout.WEST);
        final JPanel panel3 = new JPanel();
        panel3.setLayout(new BorderLayout(0, 0));
        panel3.setPreferredSize(new Dimension(0, 10));
        root_panel.add(panel3, BorderLayout.SOUTH);
        final JPanel panel4 = new JPanel();
        panel4.setLayout(new BorderLayout(0, 0));
        panel4.setPreferredSize(new Dimension(10, 0));
        root_panel.add(panel4, BorderLayout.EAST);
        final JPanel panel5 = new JPanel();
        panel5.setLayout(new BorderLayout(0, 0));
        root_panel.add(panel5, BorderLayout.CENTER);
        final JPanel panel6 = new JPanel();
        panel6.setLayout(new BorderLayout(0, 0));
        panel6.setPreferredSize(new Dimension(250, 0));
        panel5.add(panel6, BorderLayout.EAST);
        final JToolBar toolBar1 = new JToolBar();
        toolBar1.setOrientation(1);
        panel6.add(toolBar1, BorderLayout.CENTER);
        drawLineVCheckBox = new JCheckBox();
        drawLineVCheckBox.setText("drawLineV");
        toolBar1.add(drawLineVCheckBox);
        drawLineHCheckBox = new JCheckBox();
        drawLineHCheckBox.setText("drawLineH");
        toolBar1.add(drawLineHCheckBox);
        final JPanel panel7 = new JPanel();
        panel7.setLayout(new BorderLayout(0, 0));
        panel7.setPreferredSize(new Dimension(0, 0));
        panel5.add(panel7, BorderLayout.CENTER);
        panel7.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        scroll_pane = new JScrollPane();
        panel7.add(scroll_pane, BorderLayout.CENTER);
    }

    /** @noinspection ALL */
    public JComponent $$$getRootComponent$$$() {
        return root_panel;
    }

}
